package idiet.dao;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

public class SqlStatementHelper extends DefaultHandler{
	private static Logger logger=Logger.getLogger(SqlStatementHelper.class);
	private String startQName=null;
	private String id=null;
	private Map<String,String> sql=null;
	private Map<String,String> sqlTypes=null;
	private StringBuffer content=null;
	private String statementPath="sqlStatements.xml";
	
	private SqlStatementHelper(){}
	public void setStatementPath(String statementPath) {
		this.statementPath = statementPath;
	}

	public Map<String,String> getSQLs(){
		return this.sql;
	}
	
	public Map<String,String> getSqlTypes(){
		return this.sqlTypes;
	}
	public String getSqlStatement(String sqlId){
		if(this.sql!=null){
			return this.sql.get(sqlId);
		}
		return null;
	}
	@Override
	public InputSource resolveEntity(String publicId, String systemId)
			throws IOException, SAXException {
		// TODO Auto-generated method stub
		if(logger.isDebugEnabled())
			logger.debug("public id : "+publicId+" , system id : "+systemId);
		return null;
	}

	@Override
	public void notationDecl(String name, String publicId, String systemId)
			throws SAXException {
		// TODO Auto-generated method stub
		super.notationDecl(name, publicId, systemId);
		if(logger.isDebugEnabled())
			logger.debug("name : "+name+", public id : "+publicId+" , system id : "+systemId);
	}

	@Override
	public void unparsedEntityDecl(String name, String publicId,
			String systemId, String notationName) throws SAXException {
		// TODO Auto-generated method stub
		super.unparsedEntityDecl(name, publicId, systemId, notationName);
		if(logger.isDebugEnabled())
			logger.debug("name : "+name+", public id : "+publicId);
	}

	@Override
	public void setDocumentLocator(Locator locator) {
		// TODO Auto-generated method stub
		super.setDocumentLocator(locator);
		if(logger.isDebugEnabled())
			logger.debug("locator's column number : "+locator.getColumnNumber()+" , line number : "+locator.getLineNumber());
	}

	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.startDocument();
		sql=new Hashtable<String,String>();
		this.sqlTypes=new HashMap<String,String>();
		if(logger.isDebugEnabled())
			logger.debug("start document ");
	}

	@Override
	public void endDocument() throws SAXException {
		// TODO Auto-generated method stub
		if(logger.isDebugEnabled())
			logger.debug("end document ");
	}

	@Override
	public void startPrefixMapping(String prefix, String uri)
			throws SAXException {
		// TODO Auto-generated method stub
		super.startPrefixMapping(prefix, uri);
		if(logger.isDebugEnabled())
			logger.debug("prefix : "+prefix+", uri : "+uri);
	}

	@Override
	public void endPrefixMapping(String prefix) throws SAXException {
		// TODO Auto-generated method stub
		super.endPrefixMapping(prefix);
		if(logger.isDebugEnabled())
			logger.debug("prefix : "+prefix);
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		// TODO Auto-generated method stub
		if(logger.isDebugEnabled())
			logger.debug("start element , uri : "+uri+", localName : "+localName+" , qName : "+qName+" , arrributes "+attributes.getValue("id"));
		this.startQName=qName;
		if(null!=this.startQName&&(this.startQName.equals("select")||this.startQName.equals("insert")||this.startQName.equals("update")||this.startQName.equals("delete"))){
			this.id=attributes.getValue("id");
			this.sqlTypes.put(this.id, this.startQName);
			this.content=new StringBuffer();
		}
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		// TODO Auto-generated method stub
		
		if(null!=this.startQName&&(this.startQName.equals("select")||this.startQName.equals("insert")||this.startQName.equals("update")||this.startQName.equals("delete"))){
			this.sql.put(this.id, this.content.toString());
			this.content=null;
			this.startQName=null;
		}
		if(logger.isDebugEnabled())
			logger.debug("end element , uri : "+uri+", localName : "+localName+" , qName : "+qName);
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		// TODO Auto-generated method stub
			if(null!=this.startQName&&(this.startQName.equals("select")||this.startQName.equals("insert")||this.startQName.equals("update")||this.startQName.equals("delete"))){
				this.content.append(new String(ch,start,length));
			}else{
				if(logger.isDebugEnabled())
					logger.debug("characters , ch : "+new String(ch,start,length)+", start : "+start+" , length : "+length);
			}
	}

	@Override
	public void ignorableWhitespace(char[] ch, int start, int length)
			throws SAXException {
		// TODO Auto-generated method stub
		super.ignorableWhitespace(ch, start, length);
		if(logger.isDebugEnabled())
			logger.debug("ignorable white space characters , ch : "+new String(ch)+", start : "+start+" , length : "+length);
	}

	@Override
	public void processingInstruction(String target, String data)
			throws SAXException {
		// TODO Auto-generated method stub
		super.processingInstruction(target, data);
		if(logger.isDebugEnabled())
			logger.debug("target : "+target+", data : "+data);
	}

	@Override
	public void skippedEntity(String name) throws SAXException {
		// TODO Auto-generated method stub
		super.skippedEntity(name);
		if(logger.isDebugEnabled())
			logger.debug("skiped entity  , name : "+name);
	}

	@Override
	public void warning(SAXParseException e) throws SAXException {
		// TODO Auto-generated method stub
		super.warning(e);
		logger.info(e);
		e.printStackTrace();
	}

	@Override
	public void error(SAXParseException e) throws SAXException {
		// TODO Auto-generated method stub
		super.error(e);
		logger.error(e);
		e.printStackTrace();
	}

	@Override
	public void fatalError(SAXParseException e) throws SAXException {
		// TODO Auto-generated method stub
		super.fatalError(e);
		logger.error(e);
		e.printStackTrace();
	}
	public static SqlStatementHelper loadSqlStatements(){
		
		try {
			SqlStatementHelper reader=new SqlStatementHelper();
			SAXParserFactory factory=SAXParserFactory.newInstance();
			InputStream input=reader.getClass().getResourceAsStream(reader.statementPath);
			SAXParser parser = factory.newSAXParser();
			parser.parse(input, reader);
			/*Map<String,String> sqls=reader.getSQLs();
			for(String key:sqls.keySet()){
				System.out.println("key : "+key +" , value ; "+sqls.get(key));
			}*/
			
			//logger.info("load sql statements successfully ！");
			return reader;
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			logger.error(e);
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			logger.error(e);
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.error(e);
			e.printStackTrace();
		}
		return null;
		
	}
	public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException{
		SqlStatementHelper reader=new SqlStatementHelper();
		SAXParserFactory factory=SAXParserFactory.newInstance();
		SAXParser parser=factory.newSAXParser();
		InputStream input=SqlStatementHelper.class.getResourceAsStream("/com/sincered/ams/bean/dao/sqlMapper.xml");
		parser.parse(input, reader);
		Map<String,String> sqls=reader.getSQLs();
		for(String key:sqls.keySet()){
			System.out.println("key : "+key +" , value ; "+sqls.get(key));
		}
		Map<String,String> types=reader.getSqlTypes();
		for(String key:types.keySet()){
			System.out.println(" type key : "+key +" , value ; "+types.get(key));
		}
	}
}
